<!--
 * @Description: 
 * @Author: ldx
 * @Date: 2023-03-02 21:05:41
 * @LastEditors: ldx
 * @LastEditTime: 2023-04-23 21:59:45
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <script id="vertex" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform mat4 u_viewMatrix;
    void main(){
      // 顶点位置
      gl_Position = u_viewMatrix *  a_Position;
      gl_PointSize = 3.0;
    }
  </script>
  <script id="fragment" type="x-shader/x-fragment">
    void main(){
      // 片元颜色
      gl_FragColor = vec4(1,0,0,1);
    }
  </script>
  <canvas id="canvas"></canvas>
  <script type="module">
    import { initProgram, getViewMatrix, ScaleLinear, SinFn } from '../jsm/utils.js'
    import Poly from '../jsm/Poly.js'
    import { Matrix4, Vector3, Quaternion } from 'https://unpkg.com/three/build/three.module.js';
    const canvas = document.querySelector('#canvas')
    // 设置canvas容器的宽高
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    // 获取webgl上下文
    const gl = canvas.getContext('webgl');
    // 声明将来用来清空绘图区的颜色。分别对应r,g,b,a
    gl.clearColor(0, 0, 0, 1)
    // 使用之前声明的颜色，清空绘图区
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 初始化程序对象
    initProgram(gl)

    const position = new Vector3(0.2,0.4,0.1)
    const target = new Vector3(0,0,0)
    const up = new Vector3(0,1,0)
    const viewMatrix = getViewMatrix(position,target,up)
    
     /* x,z 方向的空间坐标极值 */
    const [minPosX, maxPosX, minPosZ, maxPosZ] = [
      -0.6, 0.6, -0.6, 0.6
    ]
     /* x,z 方向的弧度极值 */
    const [minAngX, maxAngX, minAngZ, maxAngZ] = [
      0, Math.PI * 4, 0, Math.PI * 2
    ]
     /* 比例尺：将空间坐标和弧度相映射 */
    const scalerX = ScaleLinear(minPosX, minAngX, maxPosX, maxAngX)
    const scalerZ = ScaleLinear(minPosZ, minAngZ, maxPosZ, maxAngZ)

    /* 波浪对象 */
    const wave = new Poly({
      gl,
      vertices: crtVertices(),
      uniforms: {
        u_viewMatrix: {
          type: 'uniformMatrix4fv',
          value: viewMatrix
        },
      }
    })
    updateVertices()
    wave.updateBuffer()
    /* 渲染 */
    gl.clear(gl.COLOR_BUFFER_BIT)
    wave.draw()

    /* 建立顶点集合 */
    function crtVertices(offset = 0) {
      const vertices = []
      for (let z = minPosZ; z < maxPosZ; z += 0.04) {
        for (let x = minPosX; x < maxPosX; x += 0.1) {
          vertices.push(x, 0, z)
        }
      }
      return vertices
    }

     //更新顶点高度
   function updateVertices(offset = 0) {
      const { vertices } = wave
      for (let i = 0; i < vertices.length; i += 3) {
        const [posX, posZ] = [vertices[i], vertices[i + 2]]
        const angZ = -scalerZ(posZ)
        const Omega = 2
        const a = Math.sin(angZ) * 0.1 + 0.03
        const phi = scalerX(posX) + offset
        vertices[i + 1] = SinFn(a, Omega, phi)(angZ)
      }
    }

     /* 动画:偏移phi */
    let offset = 0
    !(function ani() {
      offset += 0.08
      updateVertices(offset)
      wave.updateBuffer()
      gl.clear(gl.COLOR_BUFFER_BIT)
      wave.draw()
      requestAnimationFrame(ani)
    })()
    
  </script>
</body>

</html>